"""The module used to play music"""

from PyQt4.phonon import Phonon
from PyQt4 import QtCore, QtGui
from tableDisplay import TableWidget

class MockLabel(object):
    """Mocks the label for use as a null in the music player"""
    def setText(self, txt): pass

class MusicPlayer(QtCore.QObject):
    """A simple widget to play music and signal when it needs something"""
    def __init__(self, songListing, parent=None):
        QtCore.QObject.__init__(self)
        self.songListing=songListing
        self.__audioOutput=Phonon.AudioOutput(Phonon.MusicCategory, parent)
        self.__mediaObject=Phonon.MediaObject(parent)
        Phonon.createPath(self.__mediaObject, self.__audioOutput)
        self.__mediaObject.aboutToFinish.connect(self.__queueNextSong)
        self.__mediaObject.currentSourceChanged.connect(self.__sourceChange)
        self.__currentlyPlaying=MockLabel()
        self.__nextName=''
    def playSong(self, name, location):
        """Plays a song given name and location"""
        if location==None:
            self.__mediaObject.stop()
        mediaObject=self.__mediaObject
        mediaObject.currentSourceChanged.disconnect(self.__sourceChange)
        self.__currentlyPlaying.setText(name)
        mediaObject.clearQueue()
        mediaObject.setCurrentSource(Phonon.MediaSource(location))
        mediaObject.play()
        mediaObject.currentSourceChanged.connect(self.__sourceChange)
    def __queueNextSong(self):
        """Queues the next song into the player"""
        self.__nextName, location=self.songListing.nextSong()
        self.__mediaObject.enqueue(Phonon.MediaSource(location))
    def __sourceChange(self):
        """Changes the currently playing label to display the new name"""
        self.__currentlyPlaying.setText(self.__nextName)
    def getToolbar(self, parent=None):
        """Gets the toolbar associated with this music player"""
        toolbar=QtGui.QToolBar('Music', parent)
        #Buttons
        actions=((self.songListing.rewind, 'bb', 'Previous'),
                 (self.__mediaObject.play, 'play', 'Play'),
                 (self.__mediaObject.pause, 'pause', 'Pause'),
                 (self.songListing.skip, 'ff', 'Skip'))
        for function, name, text in actions:
            action=toolbar.addAction(QtGui.QIcon('icons\\%s.png'%(name)),
                                     text)
            action.triggered.connect(function)
        toolbar.addSeparator()
        #Currently playing label
        self.__currentlyPlaying=QtGui.QLabel('', parent)
        toolbar.addWidget(self.__currentlyPlaying)
        toolbar.addSeparator()
        #Sliders
        toolbar.addWidget(Phonon.SeekSlider(self.__mediaObject))
        toolbar.addSeparator()
        toolbar.addWidget(Phonon.VolumeSlider(self.__audioOutput))
        return toolbar
    def playIfStopped(self):
        """Resumes playback if stopped"""
        if self.__mediaObject.state()==Phonon.StoppedState:
            self.playSong(*self.songListing.nextSong())

class NowPlaying(object):
    """Displays those songs that are currently to be played"""
    sFinished=QtCore.pyqtSignal()
    def __init__(self, atts, parent=None):
        self.table=TableWidget([], atts, parent)
        self.player=MusicPlayer(self, parent)
        self.table.listener=self
    def loadElements(self, elements, _):
        """Loads the elements into the player"""
        self.__index=-1
        self.__elements=list(elements)
        self.table.setElements(self.__elements[:100], False)
        self.player.playSong(*self.nextSong())
    def alternateAction(self, elements, _):
        """Adds extra elements"""
        elements=tuple(elements)
        self.table.addElements(elements)
        self.__elements.extend(elements)
        self.player.playIfStopped()
    @staticmethod
    def __elementToSong(element):
        """Returns the song details from an element"""
        return element['Name'], element['Location']
    def nextSong(self):
        """Returns the next song to be played"""
        self.__index+=1
        try:
            return self.__elementToSong(self.__elements[self.__index])
        except IndexError:
            return (None, None)
    def skip(self):
        """Skips the current song, loading the player with the next song"""
        self.player.playSong(*self.nextSong())
    def rewind(self):
        """Goes back a song"""
        self.__index-=2
        self.skip()
    def getToolbar(self, parent=None):
        return self.player.getToolbar(parent)
